#ifndef _I_SCENE_GRAPH_H_
#define _I_SCENE_GRAPH_H_

#include "../interface/I_Asset.h"
#include "../interface/I_Actor.h"
#include "../interface/I_BaseMaterial.h"

#include "../interface/I_api_Device.h"
#include "../interface/I_api_Common.h"

#include "../interface/I_api_VertexShader.h"
#include "../interface/I_api_PixelShader.h"
#include "../interface/I_api_Program.h"

#include "../interface/I_api_ShaderResourceView.h"

#include "../FastXML/FastXml.h"

#include <vector>

class I_SceneGraph : public NVSHARE::FastXmlInterface
{
protected :
	int m_nFaceCount;
	int m_nVertexCount;

	I_Buffer												*	m_pPosIdx;

	std::vector<I_Asset *>						m_AssetList;
	std::vector<I_Actor *>						m_ActorList;
	std::vector<I_BaseMaterial *>			m_BaseMaterialList;

	std::vector<I_api_VertexShader *> m_VertexShaderList;
	std::vector<I_api_PixelShader *>	m_PixelShaderList;
	std::vector<I_api_Program *>			m_ProgramList;

	I_Buffer												* m_pMatrixWS;
	I_Buffer												* m_pMatrixWSInverse;
	I_BaseMaterial									* m_pBaseMaterial;

	I_api_Device										* m_pDevice;
	I_api_Common										*	m_pCommon;

	I_SpatialTree										*	m_pActorTree;
public :
	I_SceneGraph()
	{ 
		Null();
	}
	I_SceneGraph(I_api_Device * pDevice) 
	{ 
		Null();
		m_pDevice = pDevice; 
	} 
	I_SceneGraph(I_api_Device * pDevice, I_api_Common * pCommon) 
	{ 
		Null();
		m_pDevice = pDevice; 
		m_pCommon = pCommon; 
	} 
	virtual ~I_SceneGraph() 
	{ 
		Release();
	}

	virtual void	Null()
	{
		m_pMatrixWS = NULL; 
		m_nFaceCount = m_nVertexCount = 0;
		m_pCommon = NULL;
		m_pDevice = NULL;
		m_pActorTree = NULL;
		m_pPosIdx = NULL;
	}

	virtual bool	Serialize(char * pFileName) = 0;
	virtual bool	Deserialize(char * pFileName) = 0;

	virtual void	Compress()=0;
	virtual void	Build(int nType)=0;

	virtual int		FaceCount() { return m_nFaceCount; }

	virtual void	Release() 
	{
		m_AssetList.clear();
		m_ActorList.clear();
		m_VertexShaderList.clear();
		m_PixelShaderList.clear();
		m_ProgramList.clear();
		m_BaseMaterialList.clear();

		delete m_pMatrixWS; 
		delete m_pBaseMaterial;
		delete m_pActorTree;
		Null();
	}

	virtual I_SpatialTree	*		Tree() { return m_pActorTree; } 

	virtual bool	processElement(const char *elementName, 
															 NxI32 argc, const char **argv, 
															 const char *elementData, NxI32 lineno)=0;

	virtual void	Render(C_Camera * pCamera)=0;
	virtual void	RenderBVHTree(C_Camera * pCamera, int nMaxLevel, bool bAsset = true, bool bActor = true)=0;

	virtual void	RenderBVHTreeRayTrace(C_Camera * pCamera, 
																			float3 orig, 
																			float3 dir, 
																			int maxLevel, 
																			bool empty)=0;

	virtual	void	TraceIndexedInstanced(I_Buffer * pOrig,
																			I_Buffer * pDir,
																			I_Buffer * pDepth,
																			I_Buffer * pAsset,
																			I_Buffer * pPrimitive,
																			I_Buffer * pColor,
																			bool			 cu = true)=0;

	virtual	void	TraceIndexedInstanced(float3 RayO, float3 RayD, int RayI,
																			I_Buffer * pDepth,
																			I_Buffer * pAsset,
																			I_Buffer * pPrimitive,
																			I_Buffer * pColor)=0;

	virtual	void	TraceInstanced(I_Buffer * pOrig,
		I_Buffer * pDir,
		I_Buffer * pDepth,
		I_Buffer * pAsset,
		I_Buffer * pPrimitive,
		I_Buffer * pColor,
		bool			 cu = true)=0;

	virtual	void	TraceIndexed(I_Buffer * pOrig,
														I_Buffer * pDir,
														I_Buffer * pDepth,
														I_Buffer * pAsset,
														I_Buffer * pPrimitive,
														I_Buffer * pColor)=0;


	virtual	void	TraceIndexed(float3 RayO, float3 RayD, int RayI,
														I_Buffer * pDepth,
														I_Buffer * pAsset,
														I_Buffer * pPrimitive,
														I_Buffer * pColor)=0;

	virtual	void Shade(I_api_ShaderResourceView * pDiffuse, I_api_ShaderResourceView * pWorldPos, I_api_ShaderResourceView * pWorldNormal)=0;
};

#endif